from flask import Flask, jsonify, request, render_template
import os
from concurrent.futures import ThreadPoolExecutor
from win32com.client import Dispatch
import pythoncom
import pandas as pd

app = Flask(__name__)

# 配置 ThreadPoolExecutor
executor = ThreadPoolExecutor()

def docx_to_pdf(docx_path):
    pythoncom.CoInitialize()  # 初始化 COM
    w = Dispatch('Word.Application')
    doc = w.Documents.Open(docx_path)
    new_path = os.path.splitext(docx_path)[0] + '.pdf'
    doc.SaveAs(new_path, 17)  # 17 对应 PDF 格式
    doc.Close()
    w.Quit()
    pythoncom.CoUninitialize()  # 释放 COM
    return new_path


def ppt_to_png(ppt_path):
    pythoncom.CoInitialize()  # 初始化 COM
    powerpoint = Dispatch('PowerPoint.Application')
    presentation = powerpoint.Presentations.Open(ppt_path)

    slide_filenames = []
    for i, slide in enumerate(presentation.Slides):
        slide_filename = os.path.splitext(ppt_path)[0] + f'_slide_{i + 1}.png'
        slide.Export(slide_filename, 'PNG')
        slide_filenames.append(slide_filename)

    presentation.Close()
    powerpoint.Quit()
    pythoncom.CoUninitialize()  # 释放 COM
    return slide_filenames


def doc_to_docx(f_path):
    pythoncom.CoInitialize()  # 初始化 COM
    w = Dispatch('Word.Application')
    doc = w.Documents.Open(f_path)
    new_path = os.path.splitext(f_path)[0] + '.docx'
    doc.SaveAs(new_path, 12, False, '', True, '', False, False, False, False)
    doc.Close()
    w.Quit()
    pythoncom.CoUninitialize()  # 释放 COM
    return new_path


def ppt_to_pdf(ppt_path):
    pythoncom.CoInitialize()  # 初始化 COM
    powerpoint = Dispatch('PowerPoint.Application')
    presentation = powerpoint.Presentations.Open(ppt_path)

    slide_filenames = []
    for i, slide in enumerate(presentation.Slides):
        slide_filename = os.path.splitext(ppt_path)[0] + f'_slide_{i + 1}.pdf'
        slide.Export(slide_filename, 'PDF')
        slide_filenames.append(slide_filename)

    presentation.Close()
    powerpoint.Quit()
    pythoncom.CoUninitialize()  # 释放 COM
    return slide_filenames

def pptx_to_pdf(pptx_path):
    pythoncom.CoInitialize()  # 初始化 COM
    powerpoint = Dispatch('PowerPoint.Application')
    presentation = powerpoint.Presentations.Open(pptx_path)

    pdf_path = os.path.splitext(pptx_path)[0] + '.pdf'
    presentation.SaveAs(pdf_path, 32)  # 32 对应 PDF 格式
    presentation.Close()
    powerpoint.Quit()
    pythoncom.CoUninitialize()  # 释放 COM
    return pdf_path

def to_markdown(dataframe, md_file_path):
    md_table = dataframe.to_markdown(index=False)
    with open(md_file_path, 'w', encoding='utf-8') as file:
        file.write(md_table)


def read_file(file_path, encoding='utf-8'):
    if file_path.endswith('.xls') or file_path.endswith('.xlsx'):
        return pd.read_excel(file_path)
    elif file_path.endswith('.csv'):
        return pd.read_csv(file_path, encoding=encoding)
    elif file_path.endswith('.tsv'):
        return pd.read_csv(file_path, sep='\t', encoding=encoding)
    else:
        raise ValueError('Unsupported file format')

def pptx_to_png(pptx_path):
    pythoncom.CoInitialize()  # 初始化 COM
    powerpoint = Dispatch('PowerPoint.Application')
    presentation = powerpoint.Presentations.Open(pptx_path)

    slide_filenames = []
    for i, slide in enumerate(presentation.Slides):
        slide_filename = os.path.splitext(pptx_path)[0] + f'_slide_{i + 1}.png'
        slide.Export(slide_filename, 'PNG')
        slide_filenames.append(slide_filename)

    presentation.Close()
    powerpoint.Quit()
    pythoncom.CoUninitialize()  # 释放 COM
    return slide_filenames

# 定义保存目录
save_dir = os.path.join(os.getcwd(), 'converted_files')

# 确保保存目录存在
if not os.path.exists(save_dir):
    os.makedirs(save_dir)

# 路由：提供主页
@app.route('/')
def index():
    return render_template('index.html')

@app.route('/convert', methods=['POST'])
def convert_files():
    files = request.files.getlist('files')
    target_format = request.form.get('format')
    encoding = request.form.get('encoding', 'utf-8')

    results = []

    def process_file(file):
        filename = file.filename
        temp_path = os.path.join(save_dir, filename)

        # 保存文件
        file.save(temp_path)

        # 文件处理逻辑
        try:
            if target_format == 'pdf' and filename.endswith('.docx'):
                new_path = docx_to_pdf(temp_path)
                results.append({'file': filename, 'status': 'done', 'new_path': new_path})
            elif target_format == 'pdf' and filename.endswith('.pptx'):
                new_path = pptx_to_pdf(temp_path)
                results.append({'file': filename, 'status': 'done', 'new_path': new_path})
            elif target_format == 'png' and filename.endswith('.pptx'):  # 添加 pptx 转换逻辑
                slide_filenames = pptx_to_png(temp_path)
                results.append({'file': filename, 'status': 'done', 'new_paths': slide_filenames})
            elif target_format == 'png' and filename.endswith('.ppt'):
                slide_filenames = ppt_to_png(temp_path)
                results.append({'file': filename, 'status': 'done', 'new_paths': slide_filenames})
            elif target_format == 'docx' and filename.endswith('.doc'):
                new_path = doc_to_docx(temp_path)
                results.append({'file': filename, 'status': 'done', 'new_path': new_path})
            elif target_format == 'pdf' and filename.endswith('.ppt'):
                slide_filenames = ppt_to_pdf(temp_path)
                results.append({'file': filename, 'status': 'done', 'new_paths': slide_filenames})
            elif target_format == 'md' and filename.endswith(('.xls', '.xlsx', '.csv', '.tsv')):
                dataframe = read_file(temp_path, encoding)
                md_path = os.path.join(save_dir, f'{os.path.splitext(filename)[0]}.md')
                to_markdown(dataframe, md_path)
                results.append({'file': filename, 'status': 'done', 'new_path': md_path})
            else:
                results.append({'file': filename, 'status': 'undone', 'error': '不支持的转换或格式'})
        except Exception as e:
            results.append({'file': filename, 'status': 'undone', 'error': str(e)})
        finally:
            os.remove(temp_path)  # 清理临时文件

    # 用线程池执行并发任务
    with ThreadPoolExecutor() as executor:
        executor.map(process_file, files)

    # 确保返回有效的响应
    if not results:
        return jsonify({'status': 'error', 'message': 'No files processed'}), 400
    return jsonify(results)


if __name__ == '__main__':
    app.run(debug=True)
